<?php
include 'exception.php';
class SSKImageException extends SSKCustomException{};
define('SSK_IMAGE_RESIZE_AUTO', 'auto');
define('SSK_IMAGE_RESIZE_PORTRAIT', 'portrait');
define('SSK_IMAGE_RESIZE_LANDSCAPE', 'landscape');
define('SSK_IMAGE_RESIZE_CROP', 'crop');
define('SSK_IMAGE_RESIZE_FIXED', 'fixed');
class Image {
	private $image = null;
	private $tmpimg = null;
	private $filepath = null;
	private $type = null;
	private $width = 0;
	private $height = 0;
	private $w = 0;
	private $h = 0;
	
	public function __construct($filename) {
		$this->filepath = $filename;
		$size = getimagesize($this->filepath);
		$this->type = $size['mime'];
		switch($this->type) {
			case 'image/jpeg':
				$this->image = imagecreatefromjpeg($this->filepath);
				break;
			case 'image/png':
				$this->image = imagecreatefrompng($this->filepath);
				break;
			case 'image/gif':
				$this->image = imagecreatefromgif($this->filepath);
				break;
			default:
				throw new SSKImageException($this->filepath.' is not a recognized image type.');
		}
	}
	public function __destruct() {
		$this->Close();
	}
	public function Resize($width, $height, $mode=SSK_IMAGE_RESIZE_AUTO) {
		$opt = $this->getDimensions($width, $height, $mode);
		$w = $opt[0];
		$h = $opt[1];
		$this->w=$w;
		$this->h=$h;
		$this->tmpimg = imagecreatetruecolor($w,$h);
		imagecopyresampled($this->tmpimg, $this->image, 0, 0, 0, 0, $w, $h, $this->width, $this->height);
		if($mode == SSK_IMAGE_RESIZE_CROP) {
			$this->resizecrop($w, $h, $width, $height);
		}
	}
	public function Save() {
		$this->SaveAs($this->filepath);
	}
	private function resizecrop($w, $h, $width, $height) {
		$cropx=($w/2)-($width/2);
		$cropy=($h/2)-($height/2);
		$crop = $this->tmpimg;
		$this->tmpimg = imagecreatetruecolor($width, $height);
		imagecopyresampled($this->tmpimg, $crop, 0, 0, $cropx, $cropy, $width, $height, $width, $height);
	}
	public function SaveAs($path) {
		if($this->tmpimg) {
			$ext=strtolower(strrchr($path, '.'));
			switch($ext) {
				case '.jpeg':
				case '.jpg':
					imagejpeg($this->tmpimg, $path);
					break;
				case '.gif':
					imagegif($this->tmpimg, $path);
					break;
				case '.png':
					imagepng($this->tmpimg, $path);
					break;
				default:
					throw new SSKImageException("Can't save to '$path': Invalid file extension specified.");
					break;
			}
			imagedestroy($this->image);
			$this->tmpimg=$this->image;
			$this->w=$this->width;
			$this->h=$this->height;
		}
	}
	public function Close() {
		imagedestroy($this->image);
		imagedestroy($this->tmpimg);
	}
	private function getDimensions($w,$h,$m) {
		switch ($m) {
			case SSK_IMAGE_RESIZE_FIXED:
				$width = $w;
				$height= $h;
				break;
			case SSK_IMAGE_RESIZE_PORTRAIT:
				$width = $this->getSizeByFixedHeight($h);
				$height= $h;
				break;
			case SSK_IMAGE_RESIZE_LANDSCAPE:
				$width = $w;
				$height= $this->getSizeByFixedWidth($w);
				break;
			case SSK_IMAGE_RESIZE_AUTO:
				$optarr = $this->getSizeByAuto($w, $h);
				$width = $optarr[0];
				$height = $optarr[1];
				break;
			case SSK_IMAGE_RESIZE_CROP:
				$optionArray = $this->getOptimalCrop($w, $h);
				$width = $optarr[0];
				$height = $optarr[1];
				break;
			default:
				throw new SSKImageException("'$m' is not a valid mode.");
		}
		return array(0 => $width, 1 => $height);
	}
	private function getSizeByFixedHeight($h) {
		$ratio = $this->width / $this->height;
		return ($h*$ratio);
	}
	private function getSizeByFixedWidth($w) {
		$ratio = $this->width / $this->height;
		return ($w*$ratio);
	}
	private function getSizeByAuto($w,$h) {
		if($this->height < $this->width) {
			$nw=$w;
			$nh=$this->getSizeByFixedHeight($h);
		} elseif($this->height > $this->width) {
			$nw=$this->getSizeByFixedWidth($w);
			$nh=$h;
		} else {
			if($h < $w) {
				$nw=$w;
				$nh=$this->getSizeByFixedHeight($h);
			} elseif($h > $w) {
				$nw=$this->getSizeByFixedWidth($w);
				$nh=$h;
			} else {
				$nw=$w;
				$nh=$h;
			}
		}
		return array(0 => $nw, 1 => $nh);
	}
	private function getOptimalCrop($w,$h) {
		$hr=$this->height/$h;
		$wr=$this->width/$w;
		if($hr<$wr) {
			$r=$hr;
		} else {
			$r=$wr;
		}
		$nw=$w/$r;
		$nh=$h/$r;
		return array(0 => $nw, 1 => $nh);
	}
	public function GetWidth() {
		return $this->width;
	}
	public function GetHeight() {
		return $this->height;
	}
	public function GetPath() {
		return $this->filepath;
	}
}
?>